home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / awe2-0_1.lha / awe2-0.1 / Src / RCS / SPLAY-TREE,v < prev    next >
Text File  |  1988-09-18  |  43KB  |  1,774 lines

  1. head     1.1;
  2. access   ;
  3. symbols  ;
  4. locks    ; strict;
  5. comment  @# @;
  6.  
  7.  
  8. 1.1
  9. date     88.09.18.16.42.44;  author grunwald;  state Exp;
  10. branches ;
  11. next     ;
  12.  
  13.  
  14. desc
  15. @@
  16.  
  17.  
  18.  
  19. 1.1
  20. log
  21. @Initial revision
  22. @
  23. text
  24. @/* Written  6:23 pm  May  9, 1988 by rsalz@@uunet.uu.net in uiucdcsc:comp.sources.unix */
  25. /* ---------- "v14i087:  Splay tree library" ---------- */
  26. Submitted-by: Dave Brower <rtech!llama!daveb>
  27. Posting-number: Volume 14, Issue 87
  28. Archive-name: splay-tree
  29.  
  30. [  Kinda like AVL or balanced tree stuff, but not really.  --r$ ]
  31.  
  32. Here is a library for working with the splay trees Tarjan talked about
  33. in his ACM Turing Lecture.  I use it for symbol tables and the like.
  34. Others might want to change the key type and the use of strcmp as the
  35. ordering function.
  36.  
  37. It is a transliteration from Pascal code given me by Doug Jones at the U
  38. of Iowa.  Send thank you notes to him as jones@@cs.uiowa.edu.
  39.  
  40. There is a man page and a Makefile for "libsptree.a."  I would be
  41. shocked, shocked indeed to find any critical system dependencies.  
  42. (Some of the statistics might want to be longs on 16 bit machines to
  43. avoid overflow).
  44.  
  45. Users must supply their own emalloc() function.  The cavalier might
  46. do "-Demalloc=malloc" during the compilation.
  47.  
  48. -dB
  49.  
  50. #!/bin/sh
  51. # This is a shell archive, meaning:
  52. # 1. Remove everything above the #!/bin/sh line.
  53. # 2. Save the resulting text in a file.
  54. # 3. Execute the file with /bin/sh (not csh) to create the files:
  55. #    Makefile
  56. #    spaux.c
  57. #    spdaveb.c
  58. #    sptree.3
  59. #    sptree.c
  60. #    sptree.h
  61. # This archive created: Wed Feb 10 19:41:38 1988
  62. export PATH; PATH=/bin:$PATH
  63. if test -f 'Makefile'
  64. then
  65.     echo shar: over-writing existing file "'Makefile'"
  66. fi
  67. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  68. X#
  69. X# makefile for splay tree library
  70. X
  71. Xall:    libsptree.a
  72. X
  73. Xlibsptree.a:    sptree.o spaux.o spdaveb.o
  74. X    ar rvu libsptree.a sptree.o spaux.o spdaveb.o
  75. X
  76. SHAR_EOF
  77. if test -f 'spaux.c'
  78. then
  79.     echo shar: over-writing existing file "'spaux.c'"
  80. fi
  81. sed 's/^X//' << \SHAR_EOF > 'spaux.c'
  82. X/*
  83. X  spaux.c:  This code implements the following operations on an event-set
  84. X  or priority-queue implemented using splay trees:
  85. X  
  86. X  n = sphead( q )        n is the head item in q (not removed).
  87. X  spdelete( n, q )        n is removed from q.
  88. X  n = spnext( np, q )        n is the successor of np in q.
  89. X  n = spprev( np, q )        n is the predecessor of np in q.
  90. X  spenqbefore( n, np, q )    n becomes the predecessor of np in q.
  91. X  spenqafter( n, np, q )    n becomes the successor of np in q.
  92. X  
  93. X  In the above, n and np are pointers to single items (type
  94. X  SPBLK *); q is an event-set (type SPTREE *),
  95. X  The type definitions for these are taken
  96. X  from file sptree.h.  All of these operations rest on basic
  97. X  splay tree operations from file sptree.c.
  98. X  
  99. X  The basic splay tree algorithms were originally presented in:
  100. X  
  101. X  Self Adjusting Binary Trees,
  102. X  by D. D. Sleator and R. E. Tarjan,
  103. X  Proc. ACM SIGACT Symposium on Theory
  104. X  of Computing (Boston, Apr 1983) 235-245.
  105. X  
  106. X  The operations in this package supplement the operations from
  107. X  file splay.h to provide support for operations typically needed
  108. X  on the pending event set in discrete event simulation.  See, for
  109. X  example,
  110. X  
  111. X  Introduction to Simula 67,
  112. X  by Gunther Lamprecht, Vieweg & Sohn, Braucschweig, Wiesbaden, 1981.
  113. X  (Chapter 14 contains the relevant discussion.)
  114. X  
  115. X  Simula Begin,
  116. X  by Graham M. Birtwistle, et al, Studentlitteratur, Lund, 1979.
  117. X  (Chapter 9 contains the relevant discussion.)
  118. X  
  119. X  Many of the routines in this package use the splay procedure,
  120. X  for bottom-up splaying of the queue.  Consequently, item n in
  121. X  delete and item np in all operations listed above must be in the
  122. X  event-set prior to the call or the results will be
  123. X  unpredictable (eg:  chaos will ensue).
  124. X  
  125. X  Note that, in all cases, these operations can be replaced with
  126. X  the corresponding operations formulated for a conventional
  127. X  lexicographically ordered tree.  The versions here all use the
  128. X  splay operation to ensure the amortized bounds; this usually
  129. X  leads to a very compact formulation of the operations
  130. X  themselves, but it may slow the average performance.
  131. X  
  132. X  Alternative versions based on simple binary tree operations are
  133. X  provided (commented out) for head, next, and prev, since these
  134. X  are frequently used to traverse the entire data structure, and
  135. X  the cost of traversal is independent of the shape of the
  136. X  structure, so the extra time taken by splay in this context is
  137. X  wasted.
  138. X  
  139. X  This code was written by:
  140. X  Douglas W. Jones with assistance from Srinivas R. Sataluri
  141. X  
  142. X  Translated to C by David Brower, daveb@@rtech.uucp
  143. X  
  144. X */
  145. X
  146. X# include    "sptree.h"
  147. X
  148. X
  149. X/*----------------
  150. X *
  151. X * sphead() --    return the "lowest" element in the tree.
  152. X *
  153. X *    returns a reference to the head event in the event-set q,
  154. X *    represented as a splay tree; q->root ends up pointing to the head
  155. X *    event, and the old left branch of q is shortened, as if q had
  156. X *    been splayed about the head element; this is done by dequeueing
  157. X *    the head and then making the resulting queue the right son of
  158. X *    the head returned by spdeq; an alternative is provided which
  159. X *    avoids splaying but just searches for and returns a pointer to
  160. X *    the bottom of the left branch
  161. X */
  162. XSPBLK *
  163. Xsphead( q )
  164. X
  165. Xregister SPTREE * q;
  166. X
  167. X{
  168. X    register SPBLK * x;
  169. X    
  170. X    /* splay version, good amortized bound */
  171. X    x = spdeq( q->root );
  172. X    if( x != NULL )
  173. X    {
  174. X        x->rightlink = q->root;
  175. X        x->leftlink = NULL;
  176. X        x->uplink = NULL;
  177. X        if( q->root != NULL )
  178. X        q->root->uplink = x;
  179. X    }
  180. X    q->root = x;
  181. X    
  182. X    /* alternative version, bad amortized bound,
  183. X       but faster on the average */
  184. X    
  185. X# if 0
  186. X    x = q->root;
  187. X    while( x->leftlink != NULL )
  188. X    x = x->leftlink;
  189. X# endif
  190. X    
  191. X    return( x );
  192. X    
  193. X} /* sphead */
  194. X
  195. X
  196. X
  197. X/*----------------
  198. X *
  199. X * spdelete() -- Delete node from a tree.
  200. X *
  201. X *    n is deleted from q; the resulting splay tree has been splayed
  202. X *    around its new root, which is the successor of n
  203. X *
  204. X */
  205. Xvoid
  206. Xspdelete( n, q )
  207. X
  208. Xregister SPBLK * n;
  209. Xregister SPTREE * q;
  210. X
  211. X{
  212. X    register SPBLK * x;
  213. X    
  214. X    splay( n, q );
  215. X    x = spdeq( q->root->rightlink );
  216. X    if( x == NULL )        /* empty right subtree */
  217. X    {
  218. X        q->root = q->root->leftlink;
  219. X        q->root->uplink = NULL;
  220. X    }
  221. X    else            /* non-empty right subtree */
  222. X    {
  223. X        x->uplink = NULL;
  224. X        x->leftlink = q->root->leftlink;
  225. X        x->rightlink = q->root->rightlink;
  226. X        if( x->leftlink != NULL )
  227. X        x->leftlink->uplink = x;
  228. X        if( x->rightlink != NULL )
  229. X        x->rightlink->uplink = x;
  230. X        q->root = x;
  231. X    }
  232. X    
  233. X} /* spdelete */
  234. X
  235. X
  236. X
  237. X/*----------------
  238. X *
  239. X * spnext() -- return next higer item in the tree, or NULL.
  240. X *
  241. X *    return the successor of n in q, represented as a splay tree; the
  242. X *    successor becomes the root; two alternate versions are provided,
  243. X *    one which is shorter, but slower, and one which is faster on the
  244. X *    average because it does not do any splaying
  245. X *
  246. X */
  247. XSPBLK *
  248. Xspnext( n, q )
  249. X
  250. Xregister SPBLK * n;
  251. Xregister SPTREE * q;
  252. X
  253. X{
  254. X    register SPBLK * next;
  255. X    register SPBLK * x;
  256. X    
  257. X    /* splay version */
  258. X    splay( n, q );
  259. X    x = spdeq( n->rightlink );
  260. X    if( x != NULL )
  261. X    {
  262. X        x->leftlink = n;
  263. X        n->uplink = x;
  264. X        x->rightlink = n->rightlink;
  265. X        n->rightlink = NULL;
  266. X        if( x->rightlink != NULL )
  267. X        x->rightlink->uplink = x;
  268. X        q->root = x;
  269. X        x->uplink = NULL;
  270. X    }
  271. X    next = x;
  272. X    
  273. X    /* shorter slower version;
  274. X       deleting last "if" undoes the amortized bound */
  275. X    
  276. X# if 0
  277. X    splay( n, q );
  278. X    x = n->rightlink;
  279. X    if( x != NULL )
  280. X    while( x->leftlink != NULL )
  281. X        x = x->leftlink;
  282. X    next = x;
  283. X    if( x != NULL )
  284. X    splay( x, q );
  285. X# endif
  286. X    
  287. X    return( next );
  288. X    
  289. X} /* spnext */
  290. X
  291. X
  292. X
  293. X/*----------------
  294. X *
  295. X * spprev() -- return previous node in a tree, or NULL.
  296. X *
  297. X *    return the predecessor of n in q, represented as a splay tree;
  298. X *    the predecessor becomes the root; an alternate version is
  299. X *    provided which is faster on the average because it does not do
  300. X *    any splaying
  301. X *
  302. X */
  303. XSPBLK *
  304. Xspprev( n, q )
  305. X
  306. Xregister SPBLK * n;
  307. Xregister SPTREE * q;
  308. X
  309. X{
  310. X    register SPBLK * prev;
  311. X    register SPBLK * x;
  312. X    
  313. X    /* splay version;
  314. X       note: deleting the last "if" undoes the amortized bound */
  315. X    
  316. X    splay( n, q );
  317. X    x = n->leftlink;
  318. X    if( x != NULL )
  319. X    while( x->rightlink != NULL )
  320. X        x = x->rightlink;
  321. X    prev = x;
  322. X    if( x != NULL )
  323. X    splay( x, q );
  324. X    
  325. X    return( prev );
  326. X    
  327. X} /* spprev */
  328. X
  329. X
  330. X
  331. X/*----------------
  332. X *
  333. X * spenqbefore() -- insert node before another in a tree.
  334. X *
  335. X *    returns pointer to n.
  336. X *
  337. X *    event n is entered in the splay tree q as the immediate
  338. X *    predecessor of n1; in doing so, n1 becomes the root of the tree
  339. X *    with n as its left son
  340. X *
  341. X */
  342. XSPBLK *
  343. Xspenqbefore( n, n1, q )
  344. X
  345. Xregister SPBLK * n;
  346. Xregister SPBLK * n1;
  347. Xregister SPTREE * q;
  348. X
  349. X{
  350. X    splay( n1, q );
  351. X    n->key = n1->key;
  352. X    n->leftlink = n1->leftlink;
  353. X    if( n->leftlink != NULL )
  354. X    n->leftlink->uplink = n;
  355. X    n->rightlink = NULL;
  356. X    n->uplink = n1;
  357. X    n1->leftlink = n;
  358. X    
  359. X    return( n );
  360. X    
  361. X} /* spenqbefore */
  362. X
  363. X
  364. X
  365. X/*----------------
  366. X *
  367. X * spenqafter() -- enter n after n1 in tree q.
  368. X *
  369. X *    returns a pointer to n.
  370. X *
  371. X *    event n is entered in the splay tree q as the immediate
  372. X *    successor of n1; in doing so, n1 becomes the root of the tree
  373. X *    with n as its right son
  374. X */
  375. XSPBLK *
  376. Xspenqafter( n, n1, q )
  377. X
  378. Xregister SPBLK * n;
  379. Xregister SPBLK * n1;
  380. Xregister SPTREE * q;
  381. X
  382. X{
  383. X    splay( n1, q );
  384. X    n->key = n1->key;
  385. X    n->rightlink = n1->rightlink;
  386. X    if( n->rightlink != NULL )
  387. X    n->rightlink->uplink = n;
  388. X    n->leftlink = NULL;
  389. X    n->uplink = n1;
  390. X    n1->rightlink = n;
  391. X    
  392. X    return( n );
  393. X    
  394. X} /* spenqafter */
  395. X
  396. X
  397. SHAR_EOF
  398. if test -f 'spdaveb.c'
  399. then
  400.     echo shar: over-writing existing file "'spdaveb.c'"
  401. fi
  402. sed 's/^X//' << \SHAR_EOF > 'spdaveb.c'
  403. X/*
  404. X * spdaveb.c -- daveb's new splay tree functions.
  405. X *
  406. X * The functions in this file provide an interface that is nearly
  407. X * the same as the hash library I swiped from mkmf, allowing
  408. X * replacement of one by the other.  Hey, it worked for me!
  409. X *
  410. X * splookup() -- given a key, find a node in a tree.
  411. X * spinstall() -- install an item in the tree, overwriting existing value.
  412. X * spfhead() -- fast (non-splay) find the first node in a tree.
  413. X * spftail() -- fast (non-splay) find the last node in a tree.
  414. X * spscan() -- forward scan tree from the head.
  415. X * sprscan() -- reverse scan tree from the tail.
  416. X * spfnext() -- non-splaying next.
  417. X * spfprev() -- non-splaying prev.
  418. X * spstats() -- make char string of stats for a tree.
  419. X *
  420. X * Written by David Brower, daveb@@rtech.uucp 1/88.
  421. X */
  422. X
  423. X
  424. X# include "sptree.h"
  425. X
  426. X/* USER SUPPLIED! */
  427. X
  428. Xextern char *emalloc();
  429. X
  430. X
  431. X/*----------------
  432. X *
  433. X * splookup() -- given key, find a node in a tree.
  434. X *
  435. X *    Splays the found node to the root.
  436. X */
  437. XSPBLK *
  438. Xsplookup( key, q )
  439. X
  440. Xregister char * key;
  441. Xregister SPTREE * q;
  442. X
  443. X{
  444. X    register SPBLK * n;
  445. X    register int Sct;
  446. X    register int c;
  447. X
  448. X    /* find node in the tree */
  449. X    n = q->root;
  450. X    c = ++(q->lkpcmps);
  451. X    q->lookups++;
  452. X    while( n && (Sct = STRCMP( key, n->key ) ) )
  453. X    {
  454. X    c++;
  455. X    n = ( Sct < 0 ) ? n->leftlink : n->rightlink;
  456. X    }
  457. X    q->lkpcmps = c;
  458. X
  459. X    /* reorganize tree around this node */
  460. X    if( n != NULL )
  461. X    splay( n, q );
  462. X
  463. X    return( n );
  464. X}
  465. X
  466. X
  467. X
  468. X/*----------------
  469. X *
  470. X * spinstall() -- install an entry in a tree, overwriting any existing node.
  471. X *
  472. X *    If the node already exists, replace its contents.
  473. X *    If it does not exist, then allocate a new node and fill it in.
  474. X */
  475. X
  476. XSPBLK *
  477. Xspinstall( key, data, datb, q )
  478. X
  479. Xregister char * key;
  480. Xregister char * data;
  481. Xregister char * datb;
  482. Xregister SPTREE *q;
  483. X
  484. X{
  485. X    register SPBLK *n;
  486. X
  487. X    if( NULL == ( n = splookup( key, q ) ) )
  488. X    {
  489. X    n = (SPBLK *) emalloc( sizeof( *n ) );
  490. X    n->key = key;
  491. X    n->leftlink = NULL;
  492. X    n->rightlink = NULL;
  493. X    n->uplink = NULL;
  494. X    spenq( n, q );
  495. X    }
  496. X
  497. X    n->data = data;
  498. X    n->datb = datb;
  499. X
  500. X    return( n );
  501. X}
  502. X
  503. X
  504. X
  505. X
  506. X/*----------------
  507. X *
  508. X * spfhead() --    return the "lowest" element in the tree.
  509. X *
  510. X *    returns a reference to the head event in the event-set q.
  511. X *    avoids splaying but just searches for and returns a pointer to
  512. X *    the bottom of the left branch.
  513. X */
  514. XSPBLK *
  515. Xspfhead( q )
  516. X
  517. Xregister SPTREE * q;
  518. X
  519. X{
  520. X    register SPBLK * x;
  521. X
  522. X    if( NULL != ( x = q->root ) )
  523. X    while( x->leftlink != NULL )
  524. X        x = x->leftlink;
  525. X
  526. X    return( x );
  527. X
  528. X} /* spfhead */
  529. X
  530. X
  531. X
  532. X
  533. X/*----------------
  534. X *
  535. X * spftail() -- find the last node in a tree.
  536. X *
  537. X *    Fast version does not splay result or intermediate steps.
  538. X */
  539. XSPBLK *
  540. Xspftail( q )
  541. X
  542. XSPTREE * q;
  543. X
  544. X{
  545. X    register SPBLK * x;
  546. X
  547. X
  548. X    if( NULL != ( x = q->root ) )
  549. X    while( x->rightlink != NULL )
  550. X        x = x->rightlink;
  551. X
  552. X    return( x );
  553. X
  554. X} /* spftail */
  555. X
  556. X
  557. X/*----------------
  558. X *
  559. X * spscan() -- apply a function to nodes in ascending order.
  560. X *
  561. X *    if n is given, start at that node, otherwise start from
  562. X *    the head.
  563. X */
  564. Xvoid
  565. Xspscan( f, n, q )
  566. X
  567. Xregister int (*f)();
  568. Xregister SPBLK * n;
  569. Xregister SPTREE * q;
  570. X
  571. X{
  572. X    register SPBLK * x;
  573. X
  574. X    for( x = n != NULL ? n : spfhead( q ); x != NULL ; x = spfnext( x ) )
  575. X        (*f)( x );
  576. X}
  577. X
  578. X
  579. X
  580. X/*----------------
  581. X *
  582. X * sprscan() -- apply a function to nodes in descending order.
  583. X *
  584. X *    if n is given, start at that node, otherwise start from
  585. X *    the tail.
  586. X */
  587. Xvoid
  588. Xsprscan( f, n, q )
  589. X
  590. Xregister int (*f)();
  591. Xregister SPBLK * n;
  592. Xregister SPTREE * q;
  593. X
  594. X{
  595. X    register SPBLK *x;
  596. X
  597. X    for( x = n != NULL ? n : spftail( q ); x != NULL ; x = spfprev( x ) )
  598. X        (*f)( x );
  599. X}
  600. X
  601. X
  602. X
  603. X/*----------------
  604. X *
  605. X * spfnext() -- fast return next higer item in the tree, or NULL.
  606. X *
  607. X *    return the successor of n in q, represented as a splay tree.
  608. X *    This is a fast (on average) version that does not splay.
  609. X */
  610. XSPBLK *
  611. Xspfnext( n )
  612. X
  613. Xregister SPBLK * n;
  614. X
  615. X{
  616. X    register SPBLK * next;
  617. X    register SPBLK * x;
  618. X
  619. X    /* a long version, avoids splaying for fast average,
  620. X     * poor amortized bound
  621. X     */
  622. X
  623. X    if( n == NULL )
  624. X        return( n );
  625. X
  626. X    x = n->rightlink;
  627. X    if( x != NULL )
  628. X    {
  629. X        while( x->leftlink != NULL )
  630. X        x = x->leftlink;
  631. X        next = x;
  632. X    }
  633. X    else    /* x == NULL */
  634. X    {
  635. X        x = n->uplink;
  636. X        next = NULL;
  637. X        while( x != NULL )
  638. X    {
  639. X            if( x->leftlink == n )
  640. X        {
  641. X                next = x;
  642. X                x = NULL;
  643. X            }
  644. X        else
  645. X        {
  646. X                n = x;
  647. X                x = n->uplink;
  648. X            }
  649. X        }
  650. X    }
  651. X
  652. X    return( next );
  653. X
  654. X} /* spfnext */
  655. X
  656. X
  657. X
  658. X/*----------------
  659. X *
  660. X * spfprev() -- return fast previous node in a tree, or NULL.
  661. X *
  662. X *    return the predecessor of n in q, represented as a splay tree.
  663. X *    This is a fast (on average) version that does not splay.
  664. X */
  665. XSPBLK *
  666. Xspfprev( n )
  667. X
  668. Xregister SPBLK * n;
  669. X
  670. X{
  671. X    register SPBLK * prev;
  672. X    register SPBLK * x;
  673. X
  674. X    /* a long version,
  675. X     * avoids splaying for fast average, poor amortized bound
  676. X     */
  677. X
  678. X    if( n == NULL )
  679. X        return( n );
  680. X
  681. X    x = n->leftlink;
  682. X    if( x != NULL )
  683. X    {
  684. X        while( x->rightlink != NULL )
  685. X        x = x->rightlink;
  686. X        prev = x;
  687. X    }
  688. X    else
  689. X    {
  690. X        x = n->uplink;
  691. X        prev = NULL;
  692. X        while( x != NULL )
  693. X    {
  694. X            if( x->rightlink == n )
  695. X        {
  696. X                prev = x;
  697. X                x = NULL;
  698. X            }
  699. X        else
  700. X        {
  701. X                n = x;
  702. X                x = n->uplink;
  703. X            }
  704. X        }
  705. X    }
  706. X
  707. X    return( prev );
  708. X
  709. X} /* spfprev */
  710. X
  711. X
  712. X
  713. Xchar *
  714. Xspstats( q )
  715. XSPTREE *q;
  716. X{
  717. X    static char buf[ 128 ];
  718. X    float llen;
  719. X    float elen;
  720. X    float sloops;
  721. X
  722. X    if( q == NULL )
  723. X    return("");
  724. X
  725. X    llen = q->lookups ? (float)q->lkpcmps / q->lookups : 0;
  726. X    elen = q->enqs ? (float)q->enqcmps/q->enqs : 0;
  727. X    sloops = q->splays ? (float)q->splayloops/q->splays : 0;
  728. X
  729. X    sprintf(buf, "f(%d %4.2f) i(%d %4.2f) s(%d %4.2f)",
  730. X    q->lookups, llen, q->enqs, elen, q->splays, sloops );
  731. X
  732. X    return buf;
  733. X}
  734. X
  735. SHAR_EOF
  736. if test -f 'sptree.3'
  737. then
  738.     echo shar: over-writing existing file "'sptree.3'"
  739. fi
  740. sed 's/^X//' << \SHAR_EOF > 'sptree.3'
  741. X.TH SPTREE 3  "10 February 1988"
  742. X.UC 4
  743. X.SH NAME
  744. Xspdelete, spdeq, spempty, spenq, spenqafter, spenqbefore, spenqprior,
  745. Xspfhead, spfnext, spfprev, spftail, sphead, spinit, spinstall, splay,
  746. Xsplookup, spnext, spprev, sprscan, spscan, spstats \- splay tree operations
  747. X.SH SYNOPSIS
  748. X.nf
  749. X.B #include "sptree.h"
  750. X.PP
  751. X.B void spdelete(n, q)
  752. X.B SPBLK *n;
  753. X.B SPTREE *q;
  754. X.PP
  755. X.B SPBLK *spdeq(n)
  756. X.B SPBLK *n;
  757. X.PP
  758. X.B int spempty(q)
  759. X.B SPTREE *q;
  760. X.PP
  761. X.B SPBLK *spenq(n, q)
  762. X.B SPBLK *n;
  763. X.B SPTREE *q;
  764. X.PP
  765. X.B SPBLK *spenqafter(n, n1, q)
  766. X.B SPBLK *n, *n1;
  767. X.B SPTREE *q;
  768. X.PP
  769. X.B SPBLK *spenqbefore(n, n1, q)
  770. X.B SPBLK *n, *n1;
  771. X.B SPTREE *q;
  772. X.PP
  773. X.B SPBLK *spenqprior(n, q)
  774. X.B SPBLK *n;
  775. X.B SPTREE *q;
  776. X.PP
  777. X.B SPBLK *spfhead(q)
  778. X.B SPTREE *q;
  779. X.PP
  780. X.B SPBLK *spfnext(n)
  781. X.B SPBLK *n;
  782. X.PP
  783. X.B SPBLK *spfprev(n)
  784. X.B SPBLK *n;
  785. X.PP
  786. X.B SPBLK *spftail(q)
  787. X.B SPTREE *q;
  788. X.PP
  789. X.B SPBLK *sphead(q)
  790. X.B SPTREE *q;
  791. X.PP
  792. X.B SPTREE *spinit();
  793. X.PP
  794. X.B SPBLK *spinstall(key, data, datb, q)
  795. X.B char *key, *data, *datb;
  796. X.B SPTREE *q;
  797. X.PP
  798. X.B void splay(n, q)
  799. X.B SPBLK *n;
  800. X.B SPTREE *q;
  801. X.PP
  802. X.B SPBLK *splookup(key, q)
  803. X.B char *key;
  804. X.B SPTREE *q;
  805. X.PP
  806. X.B SPBLK *spnext(n, q)
  807. X.B SPBLK *n;
  808. X.B SPTREE *q;
  809. X.PP
  810. X.B SPBLK *spprev(n, q)
  811. X.B SPBLK *n;
  812. X.B SPTREE *q;
  813. X.PP
  814. X.B void sprscan(f, n, q)
  815. X.B int (*f)();
  816. X.B SPBLK *n;
  817. X.B SPTREE *q;
  818. X.PP
  819. X.B void spscan(f, n, q)
  820. X.B int (*f)();
  821. X.B SPBLK *n;
  822. X.B SPTREE *q;
  823. X.PP
  824. X.B char *spstats(q)
  825. X.B SPTREE *q;
  826. X.PP
  827. X.fi
  828. X.SH DESCRIPTION
  829. XThese functions operate on an event\-set or priority\-queue implemented
  830. Xusing splay trees.  These are similar to avl\-trees, but are not
  831. Xconcerned with keeping the tree strictly balanced.  Instead, the tree is
  832. Xdynamically reorganized in a simple way that yields a good amortized
  833. Xbound at the expense of worst case performance.
  834. X.PP
  835. XThe SPTREE structure declared in sptree.h should only be handled
  836. Xindirectly.  A pointer to an SPTREE is returned by
  837. X.I spinit
  838. Xand should be handed blindly to other access functions.
  839. X.PP
  840. XThe nodes in a splay tree are defined by the following structure,
  841. Xdeclared in sptree.h.
  842. X.PP
  843. X.nf
  844. Xtypedef struct _spblk SPBLK;
  845. Xtypedef struct _spblk
  846. X{
  847. X    .
  848. X    .
  849. X    .
  850. X
  851. X    char    *key;
  852. X    char    *data;
  853. X    char    *datb;
  854. X};
  855. X.fi
  856. X.PP
  857. XYou should only refer to the
  858. X.I key,
  859. X.I data
  860. Xand
  861. X.I datb
  862. Xmembers.
  863. X.PP
  864. XThe
  865. X.I key
  866. Xis interpreted as a pointer to a null terminated string, and ordering is
  867. Xdetermined by calls to the usual
  868. X.I strcmp
  869. Xroutine.
  870. X.PP
  871. XNo meaning is associated with the auxiliary members
  872. X.I data
  873. Xor
  874. X.I datb,
  875. Xand you are free to stuff them with whatever good conscience and a legal
  876. Xcast will allow.
  877. X.PP
  878. X.I Spdelete
  879. Xdeletes the node
  880. X.I n
  881. Xfrom the tree
  882. X.I q.
  883. XThe resulting tree is splayed around a new root, which is the successor
  884. Xto
  885. X.I n.
  886. X.PP
  887. X.I Spdeq
  888. Xremoves and returns the head node from the sub\-tree rooted at node
  889. X.I n.
  890. X.PP
  891. X.I Spempty
  892. Xreturns non\-zero if the tree
  893. X.I q
  894. Xhas no members.
  895. X.PP
  896. X.I Spenq
  897. Xinserts node
  898. X.I n
  899. Xinto tree
  900. X.I q
  901. Xafter all other nodes with the same key.  When this is done,
  902. X.I n
  903. Xwill be the root of the tree.
  904. X.PP
  905. X.I Spenqafter
  906. Xinserts node
  907. X.I n
  908. Xas the immediate sucessor of node
  909. X.I n1
  910. Xin tree
  911. X.I q.
  912. XIn so doing,
  913. X.I n1
  914. Xbecomes the root of the tree with
  915. X.I n
  916. Xas its right son.
  917. X.PP
  918. X.I Spenqbefore
  919. Xinserts node
  920. X.I n
  921. Xas the immediate predecessor of node
  922. X.I n1
  923. Xin tree
  924. X.I q.
  925. XIn doing so,
  926. X.I n1
  927. Xbecomes the root of the tree with
  928. X.I n
  929. Xas its left son.
  930. X.PP
  931. X.I Spenqprior
  932. Xinserts node
  933. X.I n
  934. Xinto the tree
  935. X.I q
  936. Xbefore all other nodes with the same key; after this is done,
  937. X.I n
  938. Xwill be the root of the tree.
  939. X.PP
  940. X.I Spfhead
  941. Xreturns a pointer to the head element in the tree
  942. X.I q,
  943. Xbut does not splay it to the root.
  944. X.PP
  945. X.I Spfnext
  946. Xreturns a pointer to the immediate successor of node
  947. X.I n
  948. Xwithout doing any reorganization.
  949. X.PP
  950. X.I Spfprev
  951. Xreturns a pointer to the immediate predecessor of node
  952. X.I n
  953. Xwithout doing any reoganization.
  954. X.PP
  955. X.I Spftail
  956. Xreturns a reference to the last node in the tree
  957. X.I q
  958. Xwithout doing any reorganization.
  959. X.PP
  960. X.I Sphead
  961. Xreturns a pointer to the head event in the tree
  962. X.I q.
  963. XThe returned node is made the root of the tree, as if
  964. X.I q
  965. Xhad been splayed around
  966. X.I n.
  967. X.PP
  968. X.I Spinit
  969. Xcreates a new splay tree using a \fImalloc\fP\-like routine named
  970. X.I emalloc
  971. Xthat must be supplied by the user.
  972. X.PP
  973. X.I Spinstall
  974. Xinserts an entry with the key value pointed to by
  975. X.I key
  976. Xwith the auxiliary values
  977. X.I data
  978. Xand
  979. X.I datb
  980. Xinto the tree
  981. X.I q.
  982. XIf a node with the key value already exists, its auxiliarly values are
  983. Xreplaced.  If the node does not already exist, a new one is allocated
  984. Xwith \fImalloc\fP\-like function named
  985. X.I emalloc
  986. Xthat must be supplied by the user.
  987. X.PP
  988. X.I Splay
  989. Xreorganizes the tree so that node
  990. X.I n
  991. Xbecomes the root of the tree in
  992. X.I q.
  993. XResults are unpredicatable if
  994. X.I n
  995. Xis not in
  996. X.I q
  997. Xto start with.
  998. X.I Q
  999. Xis split from
  1000. X.I n
  1001. Xup to the old root, with all nodes to the left of
  1002. X.I n
  1003. Xending up in the left sub\-tree, and all nodes to the right of
  1004. X.I n
  1005. Xending up in the right sub\-tree.  The left branch of the right
  1006. Xsub\-tree and the right branch of the left sub\-tree are shortened in
  1007. Xthe process.
  1008. X.PP
  1009. X.I Splookup
  1010. Xsearches for a node containing the key value pointed to by
  1011. X.I key
  1012. Xin the tree
  1013. X.I q.
  1014. XA found node is splayed to the root and returned.  If the key is not
  1015. Xfound, the function returns NULL and no reorganization is done.
  1016. X.PP
  1017. X.I
  1018. XSpnext returns a pointer to the successor of
  1019. X.I n
  1020. Xin
  1021. X.I q.
  1022. XThe successor becomes the root of the tree.
  1023. X.PP
  1024. X.I Spprev
  1025. Xreturns the predecessor of
  1026. X.I n
  1027. Xin
  1028. X.I q.
  1029. XThe predecessor becomes the root.
  1030. X.PP
  1031. X.I Sprscan
  1032. Xapplies the function
  1033. X.I f
  1034. Xstarting at node
  1035. X.I n
  1036. Xto the members of the tree
  1037. X.I q
  1038. Xin reverse order.  If
  1039. X.I n
  1040. Xis NULL, then the scan starts at the tail of the tree.  The tree is not
  1041. Xreorganized during the reverse scan.  The function is called with one
  1042. Xargument, a pointer to an SPBLK.  Its return value is ignored.
  1043. X.PP
  1044. X.I Spscan
  1045. Xapplies the function
  1046. X.I f
  1047. Xstarting at node
  1048. X.I n
  1049. Xin tree
  1050. X.I q
  1051. Xand all successive nodes, in order.  If
  1052. X.I n
  1053. Xis NULL, then the scan starts at the head of the tree.  The tree is not
  1054. Xreorganized during the scan.  The function is called with one argument,
  1055. Xa pointer to an SPBLK.  Its return value is ignored.
  1056. X.PP
  1057. X.I Spstats
  1058. Xreturns a string of statistics on the activities in the tree
  1059. X.I q.
  1060. XIt shows how many times
  1061. X.I splookup
  1062. Xwas called, and how many comparisons were needed per call,
  1063. Xthe number of nodes that have been added with
  1064. X.I spenq
  1065. Xand the number of comparisons needed per call, and finally, the number
  1066. Xof
  1067. X.I splay
  1068. Xoperations performed, and the number of loops done in each splay.  These
  1069. Xstatistics give an indication of the average effective depth of the tree
  1070. Xfor various operations.  The function returns a pointer to a static
  1071. Xbuffer that is overwritten with each call.
  1072. X.SH AUTHORS
  1073. XThe code was originally written in Pascal by Douglas W. Jones
  1074. X(jones@@cs.uiowa.edu) with assistance from Srinivas R. Sataluri.  It was
  1075. Xtranslated to C with some new functions by Dave Brower
  1076. X(daveb@@rtech.uucp).
  1077. X.SH REFERENCES
  1078. XThe basic splay tree algorithms were originally presented in:
  1079. X.PP
  1080. X.nf
  1081. X  Self Adjusting Binary Trees,
  1082. X  by D. D. Sleator and R. E. Tarjan,
  1083. X  Proc. ACM SIGACT Symposium on Theory
  1084. X  of Computing (Boston, Apr 1983) 235-245.
  1085. X.fi
  1086. X.PP
  1087. XMore operations on priority queues were added to help support discrete
  1088. Xevent simulation.  See, for example Chapter 14 of
  1089. X.PP
  1090. X.nf
  1091. X  Introduction to Simula 67,
  1092. X  by Gunther Lamprecht,
  1093. X  Vieweg & Sohn, Braucschweig, Wiesbaden, 1981.
  1094. X.fi
  1095. X.PP
  1096. Xand Chapter 9 of
  1097. X.PP
  1098. X.nf
  1099. X  Simula Begin,
  1100. X  by Graham M. Birtwistle, et al,
  1101. X  Studentlitteratur, Lund, 1979.
  1102. X.fi
  1103. X.PP
  1104. XSplay trees are compared with other data structures in
  1105. X.PP
  1106. X.nf
  1107. X  An Empirical Comparison of Priority-Queue and Event-Set Implementations,
  1108. X  by Douglas W. Jones,
  1109. X  Comm. ACM 29, 4 (Apr. 1986) 300-311.
  1110. X.fi
  1111. SHAR_EOF
  1112. if test -f 'sptree.c'
  1113. then
  1114.     echo shar: over-writing existing file "'sptree.c'"
  1115. fi
  1116. sed 's/^X//' << \SHAR_EOF > 'sptree.c'
  1117. X/*
  1118. X *
  1119. X *  sptree.c:  The following code implements the basic operations on
  1120. X *  an event-set or priority-queue implemented using splay trees:
  1121. X *
  1122. X *  SPTREE *spinit( compare )    Make a new tree
  1123. X *  int spempty();        Is tree empty?
  1124. X *  SPBLK *spenq( n, q )    Insert n in q after all equal keys.
  1125. X *  SPBLK *spdeq( q )        Return first key in q, removing it.
  1126. X *  SPBLK *spenqprior( n, q )    Insert n in q before all equal keys.
  1127. X *  void splay( n, q )        n (already in q) becomes the root.
  1128. X *
  1129. X *  In the above, n points to an SPBLK type, while q points to an
  1130. X *  SPTREE.
  1131. X *
  1132. X *  The implementation used here is based on the implementation
  1133. X *  which was used in the tests of splay trees reported in:
  1134. X *
  1135. X *    An Empirical Comparison of Priority-Queue and Event-Set Implementations,
  1136. X *    by Douglas W. Jones, Comm. ACM 29, 4 (Apr. 1986) 300-311.
  1137. X *
  1138. X *  The changes made include the addition of the enqprior
  1139. X *  operation and the addition of up-links to allow for the splay
  1140. X *  operation.  The basic splay tree algorithms were originally
  1141. X *  presented in:
  1142. X *
  1143. X *    Self Adjusting Binary Trees,
  1144. X *        by D. D. Sleator and R. E. Tarjan,
  1145. X *            Proc. ACM SIGACT Symposium on Theory
  1146. X *            of Computing (Boston, Apr 1983) 235-245.
  1147. X *
  1148. X *  The enq and enqprior routines use variations on the
  1149. X *  top-down splay operation, while the splay routine is bottom-up.
  1150. X *  All are coded for speed.
  1151. X *
  1152. X *  Written by:
  1153. X *    Douglas W. Jones
  1154. X *
  1155. X *  Translated to C by:
  1156. X *    David Brower, daveb@@rtech.uucp
  1157. X *
  1158. X */
  1159. X
  1160. X# include "sptree.h"
  1161. X
  1162. X/* USER SUPPLIED! */
  1163. X
  1164. Xextern char *emalloc();
  1165. X
  1166. X
  1167. X/*----------------
  1168. X *
  1169. X * spinit() -- initialize an empty splay tree
  1170. X *
  1171. X */
  1172. XSPTREE *
  1173. Xspinit()
  1174. X{
  1175. X    register SPTREE * q;
  1176. X
  1177. X    q = (SPTREE *) emalloc( sizeof( *q ) );
  1178. X
  1179. X    q->lookups = 0;
  1180. X    q->lkpcmps = 0;
  1181. X    q->enqs = 0;
  1182. X    q->enqcmps = 0;
  1183. X    q->splays = 0;
  1184. X    q->splayloops = 0;
  1185. X    q->root = NULL;
  1186. X    return( q );
  1187. X}
  1188. X
  1189. X/*----------------
  1190. X *
  1191. X * spempty() -- is an event-set represented as a splay tree empty?
  1192. X */
  1193. Xint
  1194. Xspempty( q )
  1195. X
  1196. XSPTREE *q;
  1197. X
  1198. X{
  1199. X    return( q == NULL || q->root == NULL );
  1200. X}
  1201. X
  1202. X
  1203. X/*----------------
  1204. X *
  1205. X *  spenq() -- insert item in a tree.
  1206. X *
  1207. X *  put n in q after all other nodes with the same key; when this is
  1208. X *  done, n will be the root of the splay tree representing q, all nodes
  1209. X *  in q with keys less than or equal to that of n will be in the
  1210. X *  left subtree, all with greater keys will be in the right subtree;
  1211. X *  the tree is split into these subtrees from the top down, with rotations
  1212. X *  performed along the way to shorten the left branch of the right subtree
  1213. X *  and the right branch of the left subtree
  1214. X */
  1215. XSPBLK *
  1216. Xspenq( n, q )
  1217. X
  1218. Xregister SPBLK * n;
  1219. Xregister SPTREE * q;
  1220. X
  1221. X{
  1222. X    register SPBLK * left;    /* the rightmost node in the left tree */
  1223. X    register SPBLK * right;    /* the leftmost node in the right tree */
  1224. X    register SPBLK * next;    /* the root of the unsplit part */
  1225. X    register SPBLK * temp;
  1226. X
  1227. X    register char * key;
  1228. X    register int Sct;        /* Strcmp value */
  1229. X
  1230. X    q->enqs++;
  1231. X    n->uplink = NULL;
  1232. X    next = q->root;
  1233. X    q->root = n;
  1234. X    if( next == NULL )    /* trivial enq */
  1235. X    {
  1236. X        n->leftlink = NULL;
  1237. X        n->rightlink = NULL;
  1238. X    }
  1239. X    else        /* difficult enq */
  1240. X    {
  1241. X        key = n->key;
  1242. X        left = n;
  1243. X        right = n;
  1244. X
  1245. X        /* n's left and right children will hold the right and left
  1246. X       splayed trees resulting from splitting on n->key;
  1247. X       note that the children will be reversed! */
  1248. X
  1249. X    q->enqcmps++;
  1250. X        if ( STRCMP( next->key, key ) > 0 )
  1251. X        goto two;
  1252. X
  1253. X    one:    /* assert next->key <= key */
  1254. X
  1255. X    do    /* walk to the right in the left tree */
  1256. X    {
  1257. X            temp = next->rightlink;
  1258. X            if( temp == NULL )
  1259. X        {
  1260. X                left->rightlink = next;
  1261. X                next->uplink = left;
  1262. X                right->leftlink = NULL;
  1263. X                goto done;    /* job done, entire tree split */
  1264. X            }
  1265. X
  1266. X        q->enqcmps++;
  1267. X            if( STRCMP( temp->key, key ) > 0 )
  1268. X        {
  1269. X                left->rightlink = next;
  1270. X                next->uplink = left;
  1271. X                left = next;
  1272. X                next = temp;
  1273. X                goto two;    /* change sides */
  1274. X            }
  1275. X
  1276. X            next->rightlink = temp->leftlink;
  1277. X            if( temp->leftlink != NULL )
  1278. X            temp->leftlink->uplink = next;
  1279. X            left->rightlink = temp;
  1280. X            temp->uplink = left;
  1281. X            temp->leftlink = next;
  1282. X            next->uplink = temp;
  1283. X            left = temp;
  1284. X            next = temp->rightlink;
  1285. X            if( next == NULL )
  1286. X        {
  1287. X                right->leftlink = NULL;
  1288. X                goto done;    /* job done, entire tree split */
  1289. X            }
  1290. X
  1291. X        q->enqcmps++;
  1292. X
  1293. X    } while( STRCMP( next->key, key ) <= 0 );    /* change sides */
  1294. X
  1295. X    two:    /* assert next->key > key */
  1296. X
  1297. X    do    /* walk to the left in the right tree */
  1298. X    {
  1299. X            temp = next->leftlink;
  1300. X            if( temp == NULL )
  1301. X        {
  1302. X                right->leftlink = next;
  1303. X                next->uplink = right;
  1304. X                left->rightlink = NULL;
  1305. X                goto done;    /* job done, entire tree split */
  1306. X            }
  1307. X
  1308. X        q->enqcmps++;
  1309. X            if( STRCMP( temp->key, key ) <= 0 )
  1310. X        {
  1311. X                right->leftlink = next;
  1312. X                next->uplink = right;
  1313. X                right = next;
  1314. X                next = temp;
  1315. X                goto one;    /* change sides */
  1316. X            }
  1317. X            next->leftlink = temp->rightlink;
  1318. X            if( temp->rightlink != NULL )
  1319. X            temp->rightlink->uplink = next;
  1320. X            right->leftlink = temp;
  1321. X            temp->uplink = right;
  1322. X            temp->rightlink = next;
  1323. X            next->uplink = temp;
  1324. X            right = temp;
  1325. X            next = temp->leftlink;
  1326. X            if( next == NULL )
  1327. X        {
  1328. X                left->rightlink = NULL;
  1329. X                goto done;    /* job done, entire tree split */
  1330. X            }
  1331. X
  1332. X        q->enqcmps++;
  1333. X
  1334. X    } while( STRCMP( next->key, key ) > 0 );    /* change sides */
  1335. X
  1336. X        goto one;
  1337. X
  1338. X    done:    /* split is done, branches of n need reversal */
  1339. X
  1340. X        temp = n->leftlink;
  1341. X        n->leftlink = n->rightlink;
  1342. X        n->rightlink = temp;
  1343. X    }
  1344. X
  1345. X    return( n );
  1346. X
  1347. X} /* spenq */
  1348. X
  1349. X
  1350. X/*----------------
  1351. X *
  1352. X *  spdeq() -- return and remove head node from a subtree.
  1353. X *
  1354. X *  remove and return the head node from the node set; this deletes
  1355. X *  (and returns) the leftmost node from q, replacing it with its right
  1356. X *  subtree (if there is one); on the way to the leftmost node, rotations
  1357. X *  are performed to shorten the left branch of the tree
  1358. X */
  1359. XSPBLK *
  1360. Xspdeq( n )
  1361. X
  1362. Xregister SPBLK * n;
  1363. X
  1364. X{
  1365. X    register SPBLK * deq;        /* one to return */
  1366. X    register SPBLK * next;           /* the next thing to deal with */
  1367. X    register SPBLK * left;          /* the left child of next */
  1368. X    register SPBLK * farleft;        /* the left child of left */
  1369. X    register SPBLK * farfarleft;    /* the left child of farleft */
  1370. X
  1371. X    if( n == NULL )
  1372. X    {
  1373. X        deq = NULL;
  1374. X    }
  1375. X    else
  1376. X    {
  1377. X        next = n;
  1378. X        left = next->leftlink;
  1379. X        if( left == NULL )
  1380. X    {
  1381. X            deq = next;
  1382. X            n = next->rightlink;
  1383. X            if( n != NULL )
  1384. X        n->uplink = NULL;
  1385. X        }
  1386. X    else for(;;)
  1387. X    {
  1388. X            /* next is not it, left is not NULL, might be it */
  1389. X            farleft = left->leftlink;
  1390. X            if( farleft == NULL )
  1391. X        {
  1392. X                deq = left;
  1393. X                next->leftlink = left->rightlink;
  1394. X                if( left->rightlink != NULL )
  1395. X            left->rightlink->uplink = next;
  1396. X        break;
  1397. X            }
  1398. X
  1399. X            /* next, left are not it, farleft is not NULL, might be it */
  1400. X            farfarleft = farleft->leftlink;
  1401. X            if( farfarleft == NULL )
  1402. X        {
  1403. X                deq = farleft;
  1404. X                left->leftlink = farleft->rightlink;
  1405. X                if( farleft->rightlink != NULL )
  1406. X            farleft->rightlink->uplink = left;
  1407. X        break;
  1408. X            }
  1409. X
  1410. X            /* next, left, farleft are not it, rotate */
  1411. X            next->leftlink = farleft;
  1412. X            farleft->uplink = next;
  1413. X            left->leftlink = farleft->rightlink;
  1414. X            if( farleft->rightlink != NULL )
  1415. X        farleft->rightlink->uplink = left;
  1416. X            farleft->rightlink = left;
  1417. X            left->uplink = farleft;
  1418. X            next = farleft;
  1419. X            left = farfarleft;
  1420. X    }
  1421. X    }
  1422. X
  1423. X    return( deq );
  1424. X
  1425. X} /* spdeq */
  1426. X
  1427. X
  1428. X/*----------------
  1429. X *
  1430. X *  spenqprior() -- insert into tree before other equal keys.
  1431. X *
  1432. X *  put n in q before all other nodes with the same key; after this is
  1433. X *  done, n will be the root of the splay tree representing q, all nodes in
  1434. X *  q with keys less than that of n will be in the left subtree, all with
  1435. X *  greater or equal keys will be in the right subtree; the tree is split
  1436. X *  into these subtrees from the top down, with rotations performed along
  1437. X *  the way to shorten the left branch of the right subtree and the right
  1438. X *  branch of the left subtree; the logic of spenqprior is exactly the
  1439. X *  same as that of spenq except for a substitution of comparison
  1440. X *  operators
  1441. X */
  1442. XSPBLK *
  1443. Xspenqprior( n, q )
  1444. X
  1445. Xregister SPBLK * n;
  1446. XSPTREE * q;
  1447. X
  1448. X{
  1449. X
  1450. X    register SPBLK * left;    /* the rightmost node in the left tree */
  1451. X    register SPBLK * right;    /* the leftmost node in the right tree */
  1452. X    register SPBLK * next;    /* the root of unsplit part of tree */
  1453. X    register SPBLK * temp;
  1454. X    register int Sct;        /* Strcmp value */
  1455. X    register char *key;
  1456. X
  1457. X    n->uplink = NULL;
  1458. X    next = q->root;
  1459. X    q->root = n;
  1460. X    if( next == NULL )    /* trivial enq */
  1461. X    {
  1462. X        n->leftlink = NULL;
  1463. X        n->rightlink = NULL;
  1464. X    }
  1465. X    else        /* difficult enq */
  1466. X    {
  1467. X        key = n->key;
  1468. X        left = n;
  1469. X        right = n;
  1470. X
  1471. X        /* n's left and right children will hold the right and left
  1472. X       splayed trees resulting from splitting on n->key;
  1473. X       note that the children will be reversed! */
  1474. X
  1475. X        if( STRCMP( next->key, key ) >= 0 )
  1476. X        goto two;
  1477. X
  1478. X    one:    /* assert next->key < key */
  1479. X
  1480. X    do    /* walk to the right in the left tree */
  1481. X    {
  1482. X            temp = next->rightlink;
  1483. X            if( temp == NULL )
  1484. X        {
  1485. X                left->rightlink = next;
  1486. X                next->uplink = left;
  1487. X                right->leftlink = NULL;
  1488. X                goto done;    /* job done, entire tree split */
  1489. X            }
  1490. X            if( STRCMP( temp->key, key ) >= 0 )
  1491. X        {
  1492. X                left->rightlink = next;
  1493. X                next->uplink = left;
  1494. X                left = next;
  1495. X                next = temp;
  1496. X                goto two;    /* change sides */
  1497. X            }
  1498. X            next->rightlink = temp->leftlink;
  1499. X            if( temp->leftlink != NULL )
  1500. X        temp->leftlink->uplink = next;
  1501. X            left->rightlink = temp;
  1502. X            temp->uplink = left;
  1503. X            temp->leftlink = next;
  1504. X            next->uplink = temp;
  1505. X            left = temp;
  1506. X            next = temp->rightlink;
  1507. X            if( next == NULL )
  1508. X        {
  1509. X                right->leftlink = NULL;
  1510. X                goto done;    /* job done, entire tree split */
  1511. X            }
  1512. X
  1513. X    } while( STRCMP( next->key, key ) < 0 );    /* change sides */
  1514. X
  1515. X    two:    /* assert next->key >= key */
  1516. X
  1517. X    do     /* walk to the left in the right tree */
  1518. X    {
  1519. X            temp = next->leftlink;
  1520. X            if( temp == NULL )
  1521. X        {
  1522. X                right->leftlink = next;
  1523. X                next->uplink = right;
  1524. X                left->rightlink = NULL;
  1525. X                goto done;    /* job done, entire tree split */
  1526. X            }
  1527. X            if( STRCMP( temp->key, key ) < 0 )
  1528. X        {
  1529. X                right->leftlink = next;
  1530. X                next->uplink = right;
  1531. X                right = next;
  1532. X                next = temp;
  1533. X                goto one;    /* change sides */
  1534. X            }
  1535. X            next->leftlink = temp->rightlink;
  1536. X            if( temp->rightlink != NULL )
  1537. X        temp->rightlink->uplink = next;
  1538. X            right->leftlink = temp;
  1539. X            temp->uplink = right;
  1540. X            temp->rightlink = next;
  1541. X            next->uplink = temp;
  1542. X            right = temp;
  1543. X            next = temp->leftlink;
  1544. X            if( next == NULL )
  1545. X        {
  1546. X                left->rightlink = NULL;
  1547. X                goto done;    /* job done, entire tree split */
  1548. X            }
  1549. X
  1550. X    } while( STRCMP( next->key, key ) >= 0 );    /* change sides */
  1551. X
  1552. X        goto one;
  1553. X
  1554. X    done:    /* split is done, branches of n need reversal */
  1555. X
  1556. X        temp = n->leftlink;
  1557. X        n->leftlink = n->rightlink;
  1558. X        n->rightlink = temp;
  1559. X    }
  1560. X
  1561. X    return( n );
  1562. X
  1563. X} /* spenqprior */
  1564. X
  1565. X/*----------------
  1566. X *
  1567. X *  splay() -- reorganize the tree.
  1568. X *
  1569. X *  the tree is reorganized so that n is the root of the
  1570. X *  splay tree representing q; results are unpredictable if n is not
  1571. X *  in q to start with; q is split from n up to the old root, with all
  1572. X *  nodes to the left of n ending up in the left subtree, and all nodes
  1573. X *  to the right of n ending up in the right subtree; the left branch of
  1574. X *  the right subtree and the right branch of the left subtree are
  1575. X *  shortened in the process
  1576. X *
  1577. X *  this code assumes that n is not NULL and is in q; it can sometimes
  1578. X *  detect n not in q and complain
  1579. X */
  1580. X
  1581. Xvoid
  1582. Xsplay( n, q )
  1583. X
  1584. Xregister SPBLK * n;
  1585. XSPTREE * q;
  1586. X
  1587. X{
  1588. X    register SPBLK * up;    /* points to the node being dealt with */
  1589. X    register SPBLK * prev;    /* a descendent of up, already dealt with */
  1590. X    register SPBLK * upup;    /* the parent of up */
  1591. X    register SPBLK * upupup;    /* the grandparent of up */
  1592. X    register SPBLK * left;    /* the top of left subtree being built */
  1593. X    register SPBLK * right;    /* the top of right subtree being built */
  1594. X
  1595. X    left = n->leftlink;
  1596. X    right = n->rightlink;
  1597. X    prev = n;
  1598. X    up = prev->uplink;
  1599. X
  1600. X    q->splays++;
  1601. X
  1602. X    while( up != NULL )
  1603. X    {
  1604. X    q->splayloops++;
  1605. X
  1606. X        /* walk up the tree towards the root, splaying all to the left of
  1607. X       n into the left subtree, all to right into the right subtree */
  1608. X
  1609. X        upup = up->uplink;
  1610. X        if( up->leftlink == prev )    /* up is to the right of n */
  1611. X    {
  1612. X            if( upup != NULL && upup->leftlink == up )  /* rotate */
  1613. X        {
  1614. X                upupup = upup->uplink;
  1615. X                upup->leftlink = up->rightlink;
  1616. X                if( upup->leftlink != NULL )
  1617. X            upup->leftlink->uplink = upup;
  1618. X                up->rightlink = upup;
  1619. X                upup->uplink = up;
  1620. X                if( upupup == NULL )
  1621. X            q->root = up;
  1622. X        else if( upupup->leftlink == upup )
  1623. X            upupup->leftlink = up;
  1624. X        else
  1625. X            upupup->rightlink = up;
  1626. X                up->uplink = upupup;
  1627. X                upup = upupup;
  1628. X            }
  1629. X            up->leftlink = right;
  1630. X            if( right != NULL )
  1631. X        right->uplink = up;
  1632. X            right = up;
  1633. X
  1634. X        }
  1635. X    else                /* up is to the left of n */
  1636. X    {
  1637. X            if( upup != NULL && upup->rightlink == up )    /* rotate */
  1638. X        {
  1639. X                upupup = upup->uplink;
  1640. X                upup->rightlink = up->leftlink;
  1641. X                if( upup->rightlink != NULL )
  1642. X            upup->rightlink->uplink = upup;
  1643. X                up->leftlink = upup;
  1644. X                upup->uplink = up;
  1645. X                if( upupup == NULL )
  1646. X            q->root = up;
  1647. X        else if( upupup->rightlink == upup )
  1648. X            upupup->rightlink = up;
  1649. X        else
  1650. X            upupup->leftlink = up;
  1651. X                up->uplink = upupup;
  1652. X                upup = upupup;
  1653. X            }
  1654. X            up->rightlink = left;
  1655. X            if( left != NULL )
  1656. X        left->uplink = up;
  1657. X            left = up;
  1658. X        }
  1659. X        prev = up;
  1660. X        up = upup;
  1661. X    }
  1662. X
  1663. X# ifdef DEBUG
  1664. X    if( q->root != prev )
  1665. X    {
  1666. X/*    fprintf(stderr, " *** bug in splay: n not in q *** " ); */
  1667. X    abort();
  1668. X    }
  1669. X# endif
  1670. X
  1671. X    n->leftlink = left;
  1672. X    n->rightlink = right;
  1673. X    if( left != NULL )
  1674. X    left->uplink = n;
  1675. X    if( right != NULL )
  1676. X    right->uplink = n;
  1677. X    q->root = n;
  1678. X    n->uplink = NULL;
  1679. X
  1680. X} /* splay */
  1681. X
  1682. SHAR_EOF
  1683. if test -f 'sptree.h'
  1684. then
  1685.     echo shar: over-writing existing file "'sptree.h'"
  1686. fi
  1687. sed 's/^X//' << \SHAR_EOF > 'sptree.h'
  1688. X/*
  1689. X** sptree.h:  The following type declarations provide the binary tree
  1690. X**  representation of event-sets or priority queues needed by splay trees
  1691. X**
  1692. X**  assumes that data and datb will be provided by the application
  1693. X**  to hold all application specific information
  1694. X**
  1695. X**  assumes that key will be provided by the application, comparable
  1696. X**  with the compare function applied to the addresses of two keys.
  1697. X*/
  1698. X
  1699. X# ifndef SPTREE_H
  1700. X# define SPTREE_H
  1701. X
  1702. X# ifndef NULL
  1703. X# define NULL    0
  1704. X# endif
  1705. X
  1706. X# define STRCMP( a, b ) ( (Sct = *(a) - *(b)) ? Sct : strcmp( (a), (b) ) )
  1707. X
  1708. Xtypedef struct _spblk SPBLK;
  1709. X
  1710. Xtypedef struct _spblk
  1711. X{
  1712. X    SPBLK    * leftlink;
  1713. X    SPBLK    * rightlink;
  1714. X    SPBLK    * uplink;
  1715. X
  1716. X    char    * key;        /* formerly time/timetyp */
  1717. X    char    * data;        /* formerly aux/auxtype */
  1718. X    char    * datb;
  1719. X};
  1720. X
  1721. Xtypedef struct
  1722. X{
  1723. X    SPBLK    * root;        /* root node */
  1724. X
  1725. X    /* Statistics, not strictly necessary, but handy for tuning  */
  1726. X
  1727. X    int        lookups;    /* number of splookup()s */
  1728. X    int        lkpcmps;    /* number of lookup comparisons */
  1729. X    
  1730. X    int        enqs;        /* number of spenq()s */
  1731. X    int        enqcmps;    /* compares in spenq */
  1732. X    
  1733. X    int        splays;
  1734. X    int        splayloops;
  1735. X
  1736. X} SPTREE;
  1737. X
  1738. X
  1739. X/* sptree.c */
  1740. Xextern SPTREE * spinit();    /* init tree */
  1741. Xextern int spempty();        /* is tree empty? */
  1742. Xextern SPBLK * spenq();        /* insert item into the tree */
  1743. Xextern SPBLK * spdeq();        /* return and remove lowest item in subtree */
  1744. Xextern SPBLK * spenqprior();    /* insert before items with same key */
  1745. Xextern void splay();        /* reorganize tree */
  1746. X
  1747. X/* spaux.c */
  1748. Xextern SPBLK * sphead();    /* return first node in tree */
  1749. Xextern void spdelete();        /* delete node from tree */
  1750. Xextern SPBLK * spnext();    /* return next node in tree */
  1751. Xextern SPBLK * spprev();    /* return previous node in tree */
  1752. Xextern SPBLK * spenqbefore();    /* enqueue before existing node */
  1753. Xextern SPBLK * spenqafter();    /* enqueue after existing node */
  1754. X
  1755. X/* spdaveb.c */
  1756. Xextern SPBLK * splookup();    /* find key in a tree */
  1757. Xextern SPBLK * spinstall();    /* enter an item, allocating or replacing */
  1758. Xextern SPBLK * sptail();    /* find end of a tree */
  1759. Xextern void spscan();        /* scan forward through tree */
  1760. Xextern void sprscan();        /* reverse scan through tree */
  1761. Xextern SPBLK * spfnext();    /* fast non-splaying next */
  1762. Xextern SPBLK * spfprev();    /* fast non-splaying prev */
  1763. X
  1764. X# endif
  1765. SHAR_EOF
  1766. #    End of shell archive
  1767. exit 0
  1768.  
  1769.  
  1770. -- 
  1771. Please send comp.sources.unix-related mail to rsalz@@uunet.uu.net.
  1772. /* End of text from uiucdcsc:comp.sources.unix */
  1773. @
  1774.